<?php

// +----------------------------------------------------------------------
// | yogurt
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Author: fengyi <1719847255.qq.com>
// +----------------------------------------------------------------------

namespace yogurt;


class Builder extends Yogurt
{
    /**
     * 框架启动方法
     * @throws Exception|\ReflectionException
     */
    public static function boot()
    {
        if ('cli' == PHP_SAPI) {
            Console::init();
            exit();
        }
        self::checkRoute();
    }

    /**
     * 检测路由
     * @throws \ReflectionException
     * @throws \yogurt\Exception
     */
    public static function checkRoute()
    {
        // 开启路由,不强制使用路由，优先使用控制器
        if (Config::get('route.use_route') && !Config::get('route.strict_route')) {
            if (!Route::checkRoute()) {
                self::run();
            }
        }
        // 开启路由，强制使用路由
        if (Config::get('route.use_route') && Config::get('route.strict_route')) {
            if (!Route::checkRoute()) {
                exit('404 page not found');
            }
        }
        // 不使用路由
        if (!Config::get('route.use_route')) {
            self::run();
        }
    }

    /**
     * @throws \ReflectionException
     * @throws \yogurt\Exception
     */
    public static function run()
    {
        // 兼容cli启动的服务
        if (isset($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], '/') === false) {
            $url = str_replace('?', '&', $_SERVER['REQUEST_URI']) ?? '';
            $url = str_replace($_SERVER['PHP_SELF'], '', $url);
        } else {
            $url = $_SERVER['QUERY_STRING'] ?? str_replace('?', '&', $_SERVER['REQUEST_URI']);
            $url = $url == 's=//' ? '/' : $url;
        }
        self::beforeExecController($url);
    }

    /**
     * 前置调用控制器方法
     * @param $url
     * @throws \ReflectionException
     * @throws \yogurt\Exception
     */
    public static function beforeExecController($url)
    {
        // 获得控制器文件
        $classNameFile = self::getFile($url);
        self::includeFile(APP_PATH . $classNameFile);
        // 获得不带后缀的控制器类
        $className = 'app\\' . self::getClass($classNameFile);
        if (!isset($obj)) {
            $obj = new $className();
        }
        // 加载composer
        if (file_exists($autoload = ROOT_PATH . 'vendor/autoload.php')) {
            self::includeFile($autoload);
        }
        // 执行控制器类的方法
        $args = self::getArgs(self::getParam($className, self::$action));
        Middleware::init($obj, $className, ['action' => self::$action, 'handle' => Config::get('middleware.handle'), 'args' => $args]);
    }

    /**
     * 获取对应参数值
     * @param $args
     * @return array
     */
    public static function getArgs($args): array
    {
        $data = [];
        foreach ($args as $a) {
            array_push($data, Request::get($a->name));
        }
        return $data;
    }

    /**
     * 获取方法参数
     * @param $class
     * @param $func
     * @return array
     * @throws \ReflectionException
     */
    public static function getParam($class, $func): array
    {
        if (method_exists($class, $func)) {
            $p = new \ReflectionMethod($class, $func);
            return $p->getParameters();
        }
        return [];

    }

    /**
     * 打印变量
     * @param $var
     * @param $exit
     * @param $format
     */
    public static function halt($var, $exit = true, $format = true)
    {
        if ($format) {
            echo '<pre>';
            print_r($var);
            echo '</pre>';
        } else {
            print_r($var);
        }
        if ($exit) {
            exit();
        }
    }

    /**
     * 获取待引入的文件
     * @param $url
     * @return string
     * @throws \yogurt\Exception
     */
    public static function getFile($url): string
    {
        $u = self::getCompatUrl($url);
        return self::getRealClassFile($u);
    }

    /**
     * 根据配置获取URL
     * @param $url
     * @return string
     * @throws \yogurt\Exception
     */
    public static function getCompatUrl($url): string
    {
        $s = self::getUrl($url);
        $uArr = explode('/', $s);
        array_pop($uArr);
        array_push($uArr, ucwords(array_pop($uArr)));
        return implode('/', $uArr);
    }
}
